package com.starsoft.frame.base.plugin;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

import com.starsoft.frame.base.bean.BaseAcount;
import com.starsoft.frame.base.service.AcountService;

@Component
public class AcountPluginService implements BeanPostProcessor{

	Logger logger = LoggerFactory.getLogger(this.getClass());

	private List<AcountPlugin> acountPlugins = new ArrayList<>();
	
	@Autowired
	private AcountService acountService;
	

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		// TODO Auto-generated method stub
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if(bean instanceof AbstractAcountPlugin){
			logger.info("Load Acount Plugin,Name[" + beanName + "], Class["
					+ bean.getClass().getName() + "]");
			acountPlugins.add((AbstractAcountPlugin) bean);
			acountPlugins.sort(new Comparator<AcountPlugin>() {
				@Override
				public int compare(AcountPlugin o1, AcountPlugin o2) {
					if (o1.getOrder() > o2.getOrder()) {
						return 1;
					} else {
						return -1;
					}
				}
			});
		}
		return bean;
	}

	public BaseAcount create(BaseAcount acount) {
		for (AcountPlugin acountPlugin : acountPlugins) {
			acountPlugin.create(acount);
		}
		return acount;
	}
	
	public void update(BaseAcount acount) {
		for (int i = acountPlugins.size() - 1; i >= 0; i--) {
			logger.info("delete call " + acountPlugins.get(i).getName());
			acountPlugins.get(i).update(acount);
		}
		updateSunAcounts(acount);
	}

	public void update(BaseAcount acount, String acountModel) {
		for (int i = acountPlugins.size() - 1; i >= 0; i--) {
			AcountPlugin acountPlugin = acountPlugins.get(i);
			logger.info("delete call " + acountPlugin.getName());
			acountPlugins.get(i).update(acount);
			if(acountPlugin.getName().equalsIgnoreCase(acountModel)){
				break;
			}
		}
		updateSunAcounts(acount);
	}
	
	public void delete(BaseAcount acount) {
		List<BaseAcount> acounts = acountService.getSunAcount(acount);
		for(BaseAcount sun: acounts){
			delete(sun);
		}
		for (int i = acountPlugins.size() - 1; i >= 0; i--) {
			logger.info("delete call " + acountPlugins.get(i).getName());
			acountPlugins.get(i).delete(acount);
		}
	}

	public void delete(BaseAcount acount, String acountModel) {
		List<BaseAcount> acounts = acountService.getSunAcount(acount);
		for(BaseAcount sun: acounts){
			delete(sun, acountModel);
		}
		for (int i = acountPlugins.size() - 1; i >= 0; i--) {
			AcountPlugin acountPlugin = acountPlugins.get(i);
			logger.info("delete call " + acountPlugin.getName());
			acountPlugins.get(i).delete(acount);
			if(acountPlugin.getName().equalsIgnoreCase(acountModel)){
				break;
			}
		}
	}

	public BaseAcount copy(BaseAcount from, BaseAcount to) {
		if (to == null) {
			to = new BaseAcount();
		}
		for (AcountPlugin acountPlugin : acountPlugins) {
			to = acountPlugin.copy(from, to);
		}
		return to;
	}

	public BaseAcount copyAsSun(BaseAcount parent, BaseAcount sun) {
		if (sun == null) {
			sun = new BaseAcount();
		}
		for (AcountPlugin acountPlugin : acountPlugins) {
			sun = acountPlugin.copyAsSun(parent, sun);
		}
		return sun;
	}

	public void updateSunAcounts(BaseAcount acount) {
		List<BaseAcount> acounts = acountService.getSunAcount(acount);
		for(BaseAcount sun: acounts){
			copyAsSun(acount, sun);
		}
	}
}
